package com.zzyl.nursing.service.impl;

import cn.hutool.core.util.IdcardUtil;
import com.alibaba.fastjson2.JSON;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.CheckInApplyDto;
import com.zzyl.nursing.dto.CheckInElderDto;
import com.zzyl.nursing.dto.ElderFamilyDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.util.CodeGeneratorUtil;
import com.zzyl.nursing.vo.CheckInConfigVo;
import com.zzyl.nursing.vo.CheckInDetailVo;
import com.zzyl.nursing.vo.CheckInElderVo;
import com.zzyl.nursing.vo.ElderFamilyVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.service.ICheckInService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 入住表Service业务层处理
 *
 * @Author: Zhy
 * @Date: 2025-02-25
 */
@Service
@RequiredArgsConstructor
public class CheckInServiceImpl extends ServiceImpl<CheckInMapper, CheckIn> implements ICheckInService {

	private final CheckInMapper checkInMapper;
	private final ElderMapper elderMapper;
	private final BedMapper bedMapper;
	private final ContractMapper contractMapper;
	private final CheckInConfigMapper checkInConfigMapper;
	private final CheckOutMapper checkOutMapper;

	private static int sort = 0;

	/**
	 * 查询入住表
	 *
	 * @param id 入住表主键
	 * @return 入住表
	 */
	@Override
	public CheckIn selectCheckInById(Long id) {
		CheckIn ci = checkInMapper.selectCheckInById(id);
		if (ci != null) {
			CheckOut co = checkOutMapper.selectCheckOutByCheckInId(ci.getId());
			if (co != null && (co.getStatus() == 1 || co.getStatus() == 2)) {
				ci.setStatus(1); // 已退住
			} else {
				ci.setStatus(0); // 已入住
			}
		}
		return ci;
	}

	/**
	 * 查询入住表列表
	 *
	 * @param checkIn 入住表
	 * @return 入住表
	 */
	@Override
	public List<CheckIn> selectCheckInList(CheckIn checkIn) {
		List<CheckIn> list = checkInMapper.selectCheckInList(checkIn);
		for (CheckIn ci : list) {
			// 查询是否有退住记录
			CheckOut co = checkOutMapper.selectCheckOutByCheckInId(ci.getId());
			if (co != null && (co.getStatus() == 1 || co.getStatus() == 2)) {
				ci.setStatus(1); // 已退住
			} else {
				ci.setStatus(0); // 已入住
			}
		}
		// 新增：如果传入了status参数，则只返回该状态的记录
		if (checkIn.getStatus() != null) {
			return list.stream().filter(ci -> ci.getStatus().equals(checkIn.getStatus())).collect(java.util.stream.Collectors.toList());
		}
		return list;
	}

	/**
	 * 新增入住表
	 *
	 * @param checkIn 入住表
	 * @return 结果
	 */
	@Override
	public int insertCheckIn(CheckIn checkIn) {
		return checkInMapper.insert(checkIn);
	}

	/**
	 * 修改入住表
	 *
	 * @param checkIn 入住表
	 * @return 结果
	 */
	@Override
	public int updateCheckIn(CheckIn checkIn) {
		return checkInMapper.updateById(checkIn);
	}

	/**
	 * 批量删除入住表
	 *
	 * @param ids 需要删除的入住表主键
	 * @return 结果
	 */
	@Override
	public int deleteCheckInByIds(Long[] ids) {
		return checkInMapper.deleteBatchIds(Arrays.asList(ids));
	}

	/**
	 * 删除入住表信息
	 *
	 * @param id 入住表主键
	 * @return 结果
	 */
	@Override
	public int deleteCheckInById(Long id) {
		// 先查出入住信息，获取床位编号
		CheckIn checkIn = checkInMapper.selectById(id);
		if (checkIn != null && checkIn.getBedNumber() != null) {
			// 通过床位编号查找床位
			Bed bed = bedMapper.selectOne(new LambdaQueryWrapper<Bed>().eq(Bed::getBedNumber, checkIn.getBedNumber()));
			if (bed != null) {
				bed.setBedStatus(0); // 0=空闲中
				bedMapper.updateById(bed);
			}
		}
		return checkInMapper.deleteById(id);
	}

	/**
	 * 申请入住
	 *
	 * @return:
	 * @param:
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void apply(CheckInApplyDto checkInApplyDto) {
		// 1. 检验老人是否已经入住
		Elder elder = checkElderIsEnable(checkInApplyDto.getCheckInElderDto().getIdCardNo());

		// 2. 检验床位状态是否已经入住
		Bed bed = checkBedIsEnable(checkInApplyDto.getCheckInConfigDto().getBedId());

		// 3. 新增或更新老人信息
		elder = updateOrInsertElder(elder, bed, checkInApplyDto.getCheckInElderDto());

		// 4. 新增签约办理
		addContract(elder, checkInApplyDto);

		// 5. 新增入住信息
		Long checkId = addCheckIn(elder, checkInApplyDto);

		// 6. 新增入住配置
		addCheckInConfig(checkId, checkInApplyDto);

		// 7. 更新床位状态为已入住
		updateBedStatus(bed.getId(), 1);
	}

	/**
	 * 新增入住配置
	 *
	 * @return:
	 * @param: checkId 入住id
	 * @param: checkInApplyDto 入住申请信息
	 */
	private void addCheckInConfig(Long checkId, CheckInApplyDto checkInApplyDto) {
		CheckInConfig checkInConfig = BeanUtil.toBean(checkInApplyDto.getCheckInConfigDto(), CheckInConfig.class);
		checkInConfig.setCheckInId(checkId);
		checkInConfig.setSortOrder(sort++);

		// 修复：insurancePayment、governmentSubsidy、otherFees 为空时赋默认值 0
		if (checkInConfig.getInsurancePayment() == null) {
			checkInConfig.setInsurancePayment(java.math.BigDecimal.ZERO);
		}
		if (checkInConfig.getGovernmentSubsidy() == null) {
			checkInConfig.setGovernmentSubsidy(java.math.BigDecimal.ZERO);
		}
		if (checkInConfig.getOtherFees() == null) {
			checkInConfig.setOtherFees(java.math.BigDecimal.ZERO);
		}
		checkInConfigMapper.insert(checkInConfig);
	}

	/**
	 * 新增入住信息
	 *
	 * @return: Long 入住id
	 * @param: elder 老人信息
	 * @param: checkInApplyDto 入住申请信息
	 */
	private Long addCheckIn(Elder elder, CheckInApplyDto checkInApplyDto) {
		CheckIn checkIn = BeanUtil.toBean(checkInApplyDto.getCheckInConfigDto(), CheckIn.class);
		checkIn.setElderName(elder.getName());
		checkIn.setElderId(elder.getId());
		checkIn.setIdCardNo(elder.getIdCardNo());
		checkIn.setBedNumber(elder.getBedNumber());
		checkIn.setStatus(0);
		checkIn.setSortOrder(sort++);

		// 家属信息
		List<ElderFamilyDto> elderFamilyDtoList = checkInApplyDto.getElderFamilyDtoList();
		checkIn.setRemark(JSON.toJSONString(elderFamilyDtoList));

		save(checkIn);

		return checkIn.getId();
	}

	/**
	 * 新增签约办理
	 *
	 * @return:
	 * @param:
	 */
	private void addContract(Elder elder, CheckInApplyDto checkInApplyDto) {
		Contract contract = BeanUtil.toBean(checkInApplyDto.getCheckInContractDto(), Contract.class);
		contract.setElderId(elder.getId().intValue());
		contract.setContractNumber(CodeGeneratorUtil.generateContractNumber());
		contract.setElderName(elder.getName());
		contract.setStartDate(checkInApplyDto.getCheckInConfigDto().getStartDate());
		contract.setEndDate(checkInApplyDto.getCheckInConfigDto().getEndDate());
		contract.setStatus(0);
		contract.setSortOrder(sort++);
		contract.setRemark("");
		// 修复：agreementPath 为空时赋值为 ""
		if (contract.getAgreementPath() == null) {
			contract.setAgreementPath("");
		}
		// 修复：contractName 为空时赋值为 "无"
		if (contract.getContractName() == null || contract.getContractName().trim().isEmpty()) {
			contract.setContractName("无");
		}
		// 修复：thirdPartyPhone 为空时赋值为 ""
		if (contract.getThirdPartyPhone() == null) {
			contract.setThirdPartyPhone("");
		}
		// 修复：thirdPartyName 为空时赋值为 ""
		if (contract.getThirdPartyName() == null) {
			contract.setThirdPartyName("");
		}
		// 修复：signDate 为空时赋默认值为当前时间
		if (contract.getSignDate() == null) {
			contract.setSignDate(java.time.LocalDateTime.now());
		}
		contractMapper.insert(contract);
	}

	/**
	 * 新增或更新老人信息
	 *
	 * @return: Elder 老人信息
	 * @param: checkInElderDto 前端传来的老人信息
	 * @param: bed 床位信息
	 */
	private Elder updateOrInsertElder(Elder elder, Bed bed, CheckInElderDto checkInElderDto) {
		if (ObjectUtil.isNotNull(elder)) {
			BeanUtil.copyProperties(checkInElderDto, elder);
		} else {
			elder = BeanUtil.toBean(checkInElderDto, Elder.class);
		}
		elder.setStatus(1);
		elder.setBedNumber(bed.getBedNumber());
		elder.setBedId(bed.getId());
		// 保证所有必填字段不为null
		if (elder.getPhone() == null) elder.setPhone("");
		if (elder.getName() == null) elder.setName("");
		if (elder.getIdCardNo() == null) elder.setIdCardNo("");
		if (elder.getSex() == null) elder.setSex(0);
		if (elder.getBirthday() == null) elder.setBirthday("");
		if (elder.getAddress() == null) elder.setAddress("");

		// 新增校验：姓名和身份证号不能为空，否则抛异常
		if (elder.getName().trim().isEmpty() || elder.getIdCardNo().trim().isEmpty()) {
			throw new BaseException("老人姓名和身份证号不能为空");
		}
		if (ObjectUtil.isNull(elder.getId())) {
			// 新增
			elderMapper.insert(elder);
		} else {
			// 更新
			elderMapper.updateById(elder);
		}
		return elder;
	}

	/**
	 * 检验床位状态是否已经入住
	 *
	 * @return: Bed 床位信息
	 * @param: bedId 床位id
	 * @param: i 床位状态
	 */
	private Bed checkBedIsEnable(Long bedId) {
		Bed bed = bedMapper.selectBedById(bedId);
		bed.setBedStatus(1);
		bedMapper.updateById(bed);
		return bed;
	}

	/**
	 * 检验老人是否已经入住
	 *
	 * @return: Elder 老人信息
	 * @param: idCardNo 身份证号
	 */
	private Elder checkElderIsEnable(String idCardNo) {
		Elder elder = elderMapper.selectOne(new LambdaQueryWrapper<Elder>().eq(Elder::getIdCardNo, idCardNo));
		if (ObjectUtil.isNotNull(elder) && elder.getStatus().equals(1)) {
			throw new BaseException("该老人已经入住，请勿重复申请");
		}
		return elder;
	}

	/**
	 * 入住详情
	 *
	 * @return:
	 * @param: id 入住id
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public CheckInDetailVo getCheckInInfo(Long id) {
		// 1. 查询入住配置信息
		CheckInConfigVo checkInConfigVo = checkInMapper.selectCheckInInfoById(id);

		// 2. 封装家属信息
		List<ElderFamilyVo> elderFamilyVoList = null;
		if (ObjectUtil.isNotNull(checkInConfigVo.getRemark())) {
			String remark = checkInConfigVo.getRemark();
			// 使用 parseArray 方法并指定泛型类型
			elderFamilyVoList = JSON.parseArray(remark, ElderFamilyVo.class);
		}

		// 3. 查询合同信息
		Contract contract = contractMapper.selectContractByElderId(id);

		// 4. 查询老人信息
		CheckInElderVo checkInElderVo = elderMapper.selectByCheckId(id);
		
		// 根据老人出生日期计算年龄，避免身份证解析错误
		if (checkInElderVo != null && checkInElderVo.getIdCardNo() != null) {
			try {
		int age = IdcardUtil.getAgeByIdCard(checkInElderVo.getIdCardNo());
		checkInElderVo.setAge(age);
			} catch (Exception e) {
				// 如果身份证解析失败，尝试从出生日期计算年龄
				if (checkInElderVo.getBirthday() != null) {
					try {
						// 假设birthday格式为yyyy-MM-dd
						String[] parts = checkInElderVo.getBirthday().split("-");
						if (parts.length == 3) {
							int birthYear = Integer.parseInt(parts[0]);
							int currentYear = java.time.LocalDate.now().getYear();
							checkInElderVo.setAge(currentYear - birthYear);
						}
					} catch (Exception ex) {
						// 如果都失败了，设置为0
						checkInElderVo.setAge(0);
					}
				} else {
					checkInElderVo.setAge(0);
				}
			}
		}

		// 5. 封装入住详情信息
		CheckInDetailVo checkInDetailVo = new CheckInDetailVo();
		checkInDetailVo.setCheckInConfigVo(checkInConfigVo);
		checkInDetailVo.setElderFamilyVoList(elderFamilyVoList);
		checkInDetailVo.setContract(contract);
		checkInDetailVo.setCheckInElderVo(checkInElderVo);

		return checkInDetailVo;
	}

	/**
	 * 根据老人ID查询入住记录
	 *
	 * @param elderId 老人ID
	 * @return 入住记录
	 */
	@Override
	public CheckIn selectCheckInByElderId(Long elderId) {
		LambdaQueryWrapper<CheckIn> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(CheckIn::getElderId, elderId);
		queryWrapper.eq(CheckIn::getStatus, 1); // 只查询在住的记录
		return this.getOne(queryWrapper);
	}

	@Override
	public List<CheckIn> selectCheckInListByStatus(int status) {
		List<CheckIn> list = this.list();
		// 动态判断状态，过滤出符合条件的记录
		return list.stream().filter(checkIn -> {
			// 查询是否有退住记录
			CheckOut checkOut = checkOutMapper.selectCheckOutByCheckInId(checkIn.getId());
			if (checkOut != null && (checkOut.getStatus() == 1 || checkOut.getStatus() == 2)) {
				// 有退住记录且状态为已批准或已退住，则入住状态为1（已退住）
				return status == 1;
			} else {
				// 没有退住记录或退住记录状态为申请中/已拒绝，则入住状态为0（已入住）
				return status == 0;
			}
		}).collect(Collectors.toList());
	}

	/**
	 * 更新床位状态
	 *
	 * @param bedId 床位ID
	 * @param status 床位状态 (0: 未入住, 1: 已入住, 2: 入住申请中)
	 */
	private void updateBedStatus(Long bedId, Integer status) {
		Bed bed = bedMapper.selectById(bedId);
		if (bed != null) {
			bed.setBedStatus(status);
			bedMapper.updateById(bed);
		}
	}

}
